package org.xjc.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.xjc.annotation.Log;
import org.xjc.config.RequestVariable;
import org.xjc.service.OperationLogService;
import org.xjc.exception.CustomException;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author : XJC
 * @Description :日志AOP
 * @create : 2022/8/21 16:41
 */

@Order(2)
@Aspect
@Component
public class LogAspect {

    @Resource
    private OperationLogService operationLogService;

    public LogAspect() {
    }

    @Pointcut("@annotation(org.xjc.annotation.Log)")
    public void logAspect() {
    }

    @Around("logAspect()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object data = null;
        long startTime = System.currentTimeMillis();
        Class<? extends Object> clazz = joinPoint.getTarget().getClass();
        Method method = getMethod(joinPoint);
        Log log = (Log) method.getAnnotation(Log.class);
        Map paramData = getParamData(joinPoint);

        data = joinPoint.proceed();
        long endTime = System.currentTimeMillis();

        try {
            operationLogService.addLog(clazz, method, log, data, endTime - startTime, paramData, RequestVariable.getRequestData().getUserId());
        } catch (Exception e) {
            throw new CustomException("操作日志保存错误，请联系管理员");
        }


        return data;
    }

    public static Log getLogData(JoinPoint joinPoint) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        return (Log) method.getAnnotation(Log.class);
    }

    public static Method getMethod(JoinPoint joinPoint) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getMethod();
    }

    public static Map<String, Object> getParamData(JoinPoint joinPoint) throws Exception {
        Map<String, Object> param = new HashMap();
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();

        for (int i = 0; i < paramNames.length; ++i) {
            param.put(paramNames[i], paramValues[i]);
        }

        return param;
    }


}


